package com.cskaoyan.javase.oop3._0abstract._1basic;

/**
 * 抽象类是作为继承体系中的,顶层父类而存在的,它是一个抽象的概念.
 * 抽象类的特点以及使用:
 * 1. 类名命名特点
 * 2. 抽象类定义时能用哪些修饰符？
 * 3. 成员特点
 *    1. 普通成员
 *    2. 静态成员
 *    3. 抽象方法
 * 4. 构造器
 * 5. 代码块
 *
 * 逐一研究:
 * 1.抽象类的命名特点,首先它是一个类名,应该遵循"大驼峰式"的命名规范.而且抽象类是一个很特殊的类
 *      为了体现这种特殊性,也能够让程序员直接通过类名得知它是抽象类
 *      抽象类的命名强烈建议,以"Abstract"或者"Base"开头
 *      比如: AbstractPerson/BasePerson
 *
 * 2.抽象类的目的就是被继承,所以final天生和abstract是不能一起使用的,比如在定义类时.
 * 3.成员特点:
 *      a.抽象类是抽象的,不能创建对象.那么它能够定义普通成员(变量和方法)吗?
 *          抽象类是可以定义普通成员的,这一点和普通类是一致的
 *          从需求的角度上来说,那些子类中共有的属性和行为,就可以提取到抽象类中
 *          尤其是方法,虽然自身不能创建对象去调用,但是可以让子类继承,然后创建子类对象去调用,作为子类的默认实现
 *          子类可以选择直接使用,也可以选择重写再使用,选择的权力在子类手中.
 *
 *      b.能不能定义静态成员?
 *          能够定义静态成员,这一点上,抽象类和普通类仍然没有区别.
 *
 *      c.抽象类是可以定义抽象方法的,那么能够不定义吗?
 *          当然可以,但是抽象类没有抽象方法有什么意义呢?
 *          如果是为了避免类创建对象,就将该类设置为抽象,合理吗?
 *          不合理
 *          什么样的类是需要设置为抽象类的?
 *          考虑继承,在继承层次中,祖先类为了体现抽象性,需要定义为抽象类(这不是一定的)
 *          抽象类就应该有抽象方法,抽象类没有抽象方法没有意义,还不如直接定义普通类.
 *
 *      d.抽象方法
 *          一个普通类继承抽象类中的抽象方法,必须继承后实现该方法(也就是重写方法)
 *          这就意味着,抽象类中的抽象方法起着约束,规范和占位的作用,一旦普通类继承抽象类,就必须实现抽象方法.
 *
 *         抽象类的子类除了可以是普通类外,也可以是一个抽象类,这样就不用实现抽象父类中的抽象方法了
 *         (当然想实现也可以,因为抽象类允许实现方法)
 *
 *         思考: abstract在修饰方法,表示抽象方法时,不能修饰什么方法?和哪些关键字冲突?
 *         抽象方法的意义就是被重写
 *              1.final,阻止方法被重写
 *              2.private,私有方法不能重写
 *                  既然抽象方法是为了被重写,所以它的访问权限往往是public
 *              3.static,静态方法不能重写
 *              4.构造方法,因为它完全不能被继承
 *
 * 4.抽象类不能创建对象,那么它有构造器吗?
 *      构造器的作用是赋值,虽然抽象类自己没有对象创建去赋值,但是它有子类
 *      子类对象在初始化时,会调用父类构造器完成父类成员变量的赋值
 *      所以抽象类也是有构造器,作用是提供给子类对象初始化时调用,它自己不能使用
 *
 *  思考:
 *      在Java中,类中一定会有什么结构? Java的类一定有构造器,包括普通类和抽象类
 *
 * 5.代码块
 *      静态代码块: 有
 *      构造代码块: 有
 *
 * 综上所述,总结抽象类的成员特点:
 *      抽象类就是比普通类多了一个抽象方法,其他地方和普通类没有区别.
 *      现在,我直接把一个类声明为抽象,在不考虑创建对象的情况下,会不会报错?
 *      不会
 *      抽象类能够继承普通类吗?
 *      可以,首先成员上没有冲突,其次即便没有继承任何类,抽象类也会继承Object
 *
 * @since 10:39
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student(100);
        System.out.println(s.a);
    }
}

// Illegal combination of modifiers: 'final' and 'abstract'
abstract class AbstractPerson {
    // 定义普通成员变量
    int a;
    private int b = 10;

    // 定义静态成员变量
    static int c;
    private int d = 20;
    static final int D = 30;

    static {
    }

    {
    }

    // 定义成员方法
    public void test() {

    }

    // 定义静态成员方法
    public static void testStatic() {

    }

    // 定义抽象方法
    public abstract void testAbstract();

    public abstract void testAbstract2();

    // 定义构造方法

    public AbstractPerson(int a, int b, int d) {
        this.a = a;
        this.b = b;
        this.d = d;
    }

    public AbstractPerson() {
        // super();
    }

    public AbstractPerson(int a) {
        this.a = a;
    }
}

// Class 'Student' must either be declared abstract or implement abstract method 'testAbstract()' in 'AbstractPerson'

class Student extends AbstractPerson {

    /*
        实现抽象方法(方法重写)的方式:
            1.写抽象类中的方法(不推荐
            2.alt+回车(推荐)
            3.alt+insert
     */
    @Override
    public void testAbstract() {
        System.out.println("我是普通类Student");
    }

    @Override
    public void testAbstract2() {
        System.out.println("我是普通类Student");
    }

    public Student(int a) {
        super(a);
    }
}

abstract class AbstractTeacher extends AbstractPerson {

}